package com.bsg.upm.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.cache.ConsulCache;
import com.bsg.upm.cache.DefinitionCache;
import com.bsg.upm.cache.DefinitionMetricCache;
import com.bsg.upm.cache.DefinitionSubServArchCache;
import com.bsg.upm.cache.DefinitionSubServUnitScaleCache;
import com.bsg.upm.cache.DefinitionSubTaskConfigCache;
import com.bsg.upm.cache.DictTypeCache;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.SubTaskDictConstants;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.constant.TaskDictConstants;
import com.bsg.upm.dao.AreaDao;
import com.bsg.upm.dao.BackupStorageDao;
import com.bsg.upm.dao.BackupStrategyDao;
import com.bsg.upm.dao.BusinessSubSystemDao;
import com.bsg.upm.dao.BusinessSystemDao;
import com.bsg.upm.dao.ClusterDao;
import com.bsg.upm.dao.ComboDao;
import com.bsg.upm.dao.DefinitionServDao;
import com.bsg.upm.dao.DefinitionSubServArchDao;
import com.bsg.upm.dao.DefinitionSubServDao;
import com.bsg.upm.dao.DefinitionSubServRelationDao;
import com.bsg.upm.dao.DefinitionSubServSoftwareDao;
import com.bsg.upm.dao.DefinitionSubServUnitScaleDao;
import com.bsg.upm.dao.DictDao;
import com.bsg.upm.dao.DictTypeDao;
import com.bsg.upm.dao.HostDao;
import com.bsg.upm.dao.NetworkingDao;
import com.bsg.upm.dao.OperateLogDao;
import com.bsg.upm.dao.OrderDao;
import com.bsg.upm.dao.PortDao;
import com.bsg.upm.dao.PrivilegeDao;
import com.bsg.upm.dao.SanDao;
import com.bsg.upm.dao.SanVendorDao;
import com.bsg.upm.dao.ServDao;
import com.bsg.upm.dao.SiteDao;
import com.bsg.upm.dao.SubOrderDao;
import com.bsg.upm.dao.SubServDao;
import com.bsg.upm.dao.SubServSoftwareImageDao;
import com.bsg.upm.dao.SubTaskDao;
import com.bsg.upm.dao.SystemDao;
import com.bsg.upm.dao.TaskDao;
import com.bsg.upm.dao.UnitDao;
import com.bsg.upm.dao.UserDao;
import com.bsg.upm.dao.UserGroupDao;
import com.bsg.upm.dao.UserRoleDao;
import com.bsg.upm.entity.DefinitionSubServRelationEntity;
import com.bsg.upm.entity.DefinitionSubServSoftwareEntity;
import com.bsg.upm.entity.DefinitionSubTaskConfigEntity;
import com.bsg.upm.entity.HostEntity;
import com.bsg.upm.entity.OperateLogEntity;
import com.bsg.upm.entity.ServEntity;
import com.bsg.upm.entity.SubServEntity;
import com.bsg.upm.entity.SubServSoftwareImageEntity;
import com.bsg.upm.entity.SubTaskEntity;
import com.bsg.upm.entity.TaskEntity;
import com.bsg.upm.entity.UnitEntity;
import com.bsg.upm.entity.UserEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.HttpClientUtils;
import com.bsg.upm.http.HttpConnectionException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;
import com.bsg.upm.util.AutoComparator;
import com.bsg.upm.util.LogUtils;
import com.bsg.upm.util.PrimaryKeyUtils;
import com.bsg.upm.util.PropertyPlaceholder;
import com.bsg.upm.util.SpringContextUtils;

import smlib.Resp;
import smlib.Smlib;

public abstract class BaseService {

	@Resource
	protected UserDao userDao;

	@Resource
	protected UserRoleDao userRoleDao;
	
	@Resource
	protected UserGroupDao userGroupDao;

	@Resource
	protected DefinitionServDao definitionServDao;

	@Resource
	protected DefinitionSubServDao definitionSubServDao;

	@Resource
	protected DefinitionSubServSoftwareDao definitionSubServSoftwareDao;

	@Resource
	protected DefinitionSubServArchDao definitionSubServArchDao;

	@Resource
	protected DefinitionSubServUnitScaleDao definitionSubServUnitScaleDao;

	@Resource
	protected DefinitionSubServRelationDao definitionSubServRelationDao;

	@Resource
	protected ComboDao comboDao;

	@Resource
	protected SiteDao siteDao;

	@Resource
	protected BackupStorageDao backupStorageDao;

	@Resource
	protected SubServSoftwareImageDao subServSoftwareImageDao;

	@Resource
	protected NetworkingDao networkingDao;

	@Resource
	protected PortDao portDao;

	@Resource
	protected SanVendorDao sanVendorDao;

	@Resource
	protected SanDao sanDao;

	@Resource
	protected AreaDao areaDao;

	@Resource
	protected ClusterDao clusterDao;

	@Resource
	protected HostDao hostDao;

	@Resource
	protected BusinessSystemDao businessSystemDao;

	@Resource
	protected BusinessSubSystemDao businessSubSystemDao;

	@Resource
	protected OrderDao orderDao;

	@Resource
	protected SubOrderDao subOrderDao;

	@Resource
	protected ServDao servDao;

	@Resource
	protected SubServDao subServDao;

	@Resource
	protected UnitDao unitDao;

	@Resource
	protected BackupStrategyDao backupStrategyDao;

	@Resource
	protected TaskDao taskDao;

	@Resource
	protected SubTaskDao subTaskDao;

	@Resource
	protected OperateLogDao operateLogDao;

	@Resource
	protected PrivilegeDao privilegeDao;

	@Resource
	protected DictTypeDao dictTypeDao;

	@Resource
	protected DictDao dictDao;

	@Resource
	protected SystemDao systemDao;

	@Resource
	protected DefinitionMetricCache definitionMetricCache;

	@Resource
	protected DictTypeCache dictTypeCache;

	@Resource
	protected DefinitionCache definitionCache;

	@Resource
	protected ConsulCache consulCache;

	@Resource
	protected DefinitionSubTaskConfigCache definitionSubTaskConfigCache;

	@Resource
	protected DefinitionSubServArchCache definitionSubServArchCache;

	@Resource
	protected DefinitionSubServUnitScaleCache definitionSubServUnitScaleCache;

	@Autowired
	protected HttpSession session;

	@Autowired
	protected DataSourceTransactionManager txManager;

	/**
	 * 日志对象
	 */
	protected Logger logger = Logger.getLogger(getClass());

	public RespJson sendHttpGet(String siteId, String interfaceType, String url, int retryCnt, int timeInvertal) {
		return sendHttp(siteId, interfaceType, url, HttpClientUtils.METHOD_GET, null, retryCnt, timeInvertal, true);
	}

	/**
	 * 发送httpGet请求
	 * 
	 * @param siteId
	 *            站点编码
	 * @param interfaceType
	 *            接口类型
	 * @param url
	 *            接口url
	 * @return 请求结果
	 */
	public RespJson sendHttpGet(String siteId, String interfaceType, String url) {
		return sendHttpGet(siteId, interfaceType, url, true);
	}

	/**
	 * 发送httpGet请求
	 * 
	 * @param siteId
	 *            站点编码
	 * @param interfaceType
	 *            接口类型
	 * @param url
	 *            接口url
	 * @return 请求结果
	 */
	public RespJson sendHttpGet(String siteId, String interfaceType, String url, boolean showLog) {
		return sendHttp(siteId, interfaceType, url, HttpClientUtils.METHOD_GET, null, 1, 0, showLog);
	}

	/**
	 * 发送httpPost的创建请求
	 * 
	 * @param siteId
	 *            站点编码
	 * @param interfaceType
	 *            接口类型
	 * @param url
	 *            接口url
	 * @param jsonParam
	 *            参数
	 * @return 请求结果
	 */
	public RespJson sendHttpPost(String siteId, String interfaceType, String url, String jsonParam) {
		return sendHttp(siteId, interfaceType, url, HttpClientUtils.METHOD_POST, jsonParam, 1, 0, true);
	}

	/**
	 * 发送httpPut请求
	 * 
	 * @param siteId
	 *            站点编码
	 * @param interfaceType
	 *            接口类型
	 * @param url
	 *            接口url
	 * @param jsonParam
	 *            参数
	 * @return 请求结果
	 */
	public RespJson sendHttpPut(String siteId, String interfaceType, String url, String jsonParam) {
		return sendHttp(siteId, interfaceType, url, HttpClientUtils.METHOD_PUT, jsonParam, 1, 0, true);
	}

	/**
	 * 发送httpDelete请求
	 * 
	 * @param siteId
	 *            站点编码
	 * @param interfaceType
	 *            接口类型
	 * @param url
	 *            接口url
	 * @return 请求结果
	 */
	public RespJson sendHttpDelete(String siteId, String interfaceType, String url) {
		return sendHttp(siteId, interfaceType, url, HttpClientUtils.METHOD_DELETE, null, 1, 0, true);
	}

	/**
	 * 获取用户信息
	 * 
	 * @return
	 */
	public UserEntity getUser() {
		return (UserEntity) session.getAttribute("user");
	}

	/**
	 * 保存操作日志
	 * 
	 * @param modelName
	 *            操作模块名称
	 * @param action
	 *            操作动作
	 * @param objId
	 *            操作对象编码
	 * @param objName
	 *            操作对象名称
	 * @return 操作日志对象
	 */
	public OperateLogEntity saveOperateLog(String modelName, String action, String objId, String objName) {
		return saveOperateLog(modelName, action, objId, objName, getUser().getUsername(),
				systemDao.getCurrentDateTime());
	}

	/**
	 * 保存操作日志
	 * 
	 * @param modelName
	 *            操作模块名称
	 * @param action
	 *            操作动作
	 * @param objId
	 *            操作对象编码
	 * @param objName
	 *            操作对象名称
	 * @param operateDateTime
	 *            操作时间
	 * @return 操作日志对象
	 */
	public OperateLogEntity saveOperateLog(String modelName, String action, String objId, String objName,
			Date operateDateTime) {
		return saveOperateLog(modelName, action, objId, objName, getUser().getUsername(),
				systemDao.getCurrentDateTime());
	}

	/**
	 * 保存操作日志
	 * 
	 * @param modelName
	 *            操作模块名称
	 * @param action
	 *            操作动作
	 * @param objId
	 *            操作对象编码
	 * @param objName
	 *            操作对象名称
	 * @param operator
	 *            操作者
	 * @param operateDateTime
	 *            操作时间
	 * @return 操作日志对象
	 */
	public OperateLogEntity saveOperateLog(String modelName, String action, String objId, String objName,
			String operator, Date operateDateTime) {
		OperateLogEntity operateLog = new OperateLogEntity();
		operateLog.setId(PrimaryKeyUtils.uniqueId());
		operateLog.setModelName(modelName);
		operateLog.setAction(action);
		operateLog.setObjId(objId);
		operateLog.setObjName(objName);
		operateLog.setCreateDateTime(operateDateTime);
		operateLog.setCreateUserLoginName(operator);
		operateLogDao.save(operateLog);
		return operateLog;
	}

	/**
	 * 获取软件镜像名和版本
	 * 
	 * @param softwareImage
	 *            软件镜像对象
	 * @return String 软件镜像名
	 */
	public String getSoftwareImageNameAndVersion(SubServSoftwareImageEntity softwareImage) {
		if (softwareImage == null) {
			return null;
		}
		DefinitionSubServSoftwareEntity dfSubServSoftware = softwareImage.getDefinitionSubServSoftware();
		String subServName = dfSubServSoftware.getDefinitionSubServName();
		String softwareImageName = subServName + "-" + dfSubServSoftware.getMajorVersion() + "."
				+ dfSubServSoftware.getMinorVersion() + "." + softwareImage.getPatchVersion() + "."
				+ softwareImage.getBuildVersion();
		return softwareImageName;
	}

	/**
	 * 获取软件镜像路径
	 * 
	 * @param dfSubServSoftware
	 *            子服务软件定义对象
	 * @param patchVersion
	 *            修订版本
	 * @param buildVersion
	 *            编译版本
	 * @return
	 */
	public String getSoftwareImagePath(SubServSoftwareImageEntity softwareImage) {
		String imagePath = null;
		DefinitionSubServSoftwareEntity dfSubServSoftware = softwareImage.getDefinitionSubServSoftware();
		String subServName = dfSubServSoftware.getDefinitionSubServName();
		String softwareImageName = getSoftwareImageNameAndVersion(softwareImage);
		String filePath = PropertyPlaceholder.getProperty("sys.software.image.path");
		String suffix = PropertyPlaceholder.getProperty("sys.software.image.suffix");
		if (filePath.endsWith("/")) {
			imagePath = filePath + subServName + "/" + softwareImageName + "." + suffix.replaceFirst(".", "");
		} else {
			imagePath = filePath + "/" + subServName + "/" + softwareImageName + "." + suffix.replaceFirst(".", "");
		}
		return imagePath;
	}

	/**
	 * 判断子任务是否超时
	 * 
	 * @param subTask
	 *            子任务对象
	 * @return
	 */
	public boolean isTimeout(SubTaskEntity subTask) {
		if (subTask.getStartDateTime() != null) {
			if (subTask.getStartDateTime().getTime() + subTask.getTimeout() < systemDao.getCurrentDateTime()
					.getTime()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 保存任务及关联的子任务
	 * 
	 * @param task
	 *            任务对象
	 */
	public void saveTask(TaskEntity task) {
		taskDao.save(task);
		if (task.getSubTasks().size() > 0) {
			taskDao.saveRelativeSubTask(task);
		}
	}

	/**
	 * 按照部署优先级升序排序
	 * 
	 * @param subServs
	 *            子服务集合
	 */
	public void sortByPriorityASC(List<SubServEntity> subServs) {
		for (int i = 0; i < subServs.size() - 1; i++) {
			for (int j = 0; j < subServs.size() - 1 - i; j++) {
				if (subServs.get(j).getSubOrder().getDefinitionSubServ().getPriority() > subServs.get(j + 1)
						.getSubOrder().getDefinitionSubServ().getPriority()) {
					SubServEntity subServ = subServs.get(j + 1);
					subServs.set(j + 1, subServs.get(j));
					subServs.set(j, subServ);
				}
			}
		}
	}

	/**
	 * 按照部署优先级降序排序
	 * 
	 * @param subServs
	 *            子服务集合
	 */
	public void sortByPriorityDESC(List<SubServEntity> subServs) {
		for (int i = 0; i < subServs.size() - 1; i++) {
			for (int j = 0; j < subServs.size() - 1 - i; j++) {
				if (subServs.get(j).getSubOrder().getDefinitionSubServ().getPriority() < subServs.get(j + 1)
						.getSubOrder().getDefinitionSubServ().getPriority()) {
					SubServEntity subServ = subServs.get(j + 1);
					subServs.set(j + 1, subServs.get(j));
					subServs.set(j, subServ);
				}
			}
		}
	}

	/**
	 * 开启任务
	 * 
	 * @param task
	 *            任务对象
	 */
	public void startTask(final TaskEntity task) {
		ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) SpringContextUtils.getBeanById("threadPool");
		taskExecutor.execute(new Runnable() {
			@Override
			public void run() {
				SubTaskEntity curSubTask = null;
				String logPrefix = null;
				try {
					// 获取子任务
					List<SubTaskEntity> subTasks = task.getSubTasks();

					// 将子任务按照部署优先级排序
					Collections.sort(subTasks, new AutoComparator("priority"));
					int subTaskSum = subTasks.size();

					// 构建log信息前缀
					logPrefix = LogUtils.formate(task, null);
					logger.info(logPrefix + " - " + "开启任务(子任务总数：" + subTaskSum + ")");

					// 获取站点
					String siteId = task.getSite().getId();

					for (int i = 0; i < subTaskSum; i++) {
						curSubTask = subTasks.get(i);

						// 构建任务描述
						String description = (i + 1) + "/" + subTaskSum + ":" + curSubTask.getActionType() + "_"
								+ curSubTask.getObjName();
						logPrefix = LogUtils.formate(task, description);
						logger.info(
								logPrefix + " - " + "执行子任务(" + (i + 1) + "/" + subTaskSum + ")【 " + description + " 】");

						// 更新子任务为开启状态
						if (curSubTask.getStartDateTime() == null) {
							updateSubTaskToStart(curSubTask, logPrefix);
						}

						// 异步任务处理
						if (curSubTask.isAsync()) {
							JSONObject respJson = null;

							// 请求方法类型
							switch (curSubTask.getMethodType()) {
							case HttpClientUtils.METHOD_POST:
								// 请求参数
								String param = curSubTask.getParam();

								if ((TaskDictConstants.ACTION_TYPE_CREATE.equals(task.getActionType())
										|| TaskDictConstants.ACTION_TYPE_REBUILD.equals(task.getActionType()))
										&& SubTaskDictConstants.ACTION_TYPE_LINK.equals(curSubTask.getActionType())) {
									ServEntity serv = (ServEntity) task.getObj();
									param = getLinkParam(serv, null);
								}

								// 发送HTTP请求
								RespJson httpRespJson = sendHttpPost(siteId, SysConstants.INTERFACE_TYPE_MGM,
										curSubTask.getUrl(), param);
								if (httpRespJson.getStatus() != HttpStatus.SC_CREATED) {
									throw new APIException(httpRespJson.getMsg());
								}
								respJson = (JSONObject) httpRespJson.getData();
								break;

							default:
								break;
							}

							// 异步子任务执行后的业务处理
							executeAfterAsyncSubTask(curSubTask, task, respJson);

							logger.info(logPrefix + " - " + "轮询MGM任务状态");

							// 获取子任务配置信息
							DefinitionSubTaskConfigEntity dfSubTaskConfig = definitionSubTaskConfigCache
									.getDfSubTaskConfigFromCache(curSubTask.getObjType(), curSubTask.getActionType());

							// 子任务关联状态
							int relateTaskStatus = SubTaskDictConstants.RELATE_STATUS_RUNNING;
							while (relateTaskStatus == SubTaskDictConstants.RELATE_STATUS_RUNNING) {
								logger.info(logPrefix + " - " + "调用MGM任务查询接口");

								// 获取MGM任务信息
								JSONObject mgmTaskInfo = getTaskInfoFromMGM(siteId, curSubTask.getRelateTaskId(),
										dfSubTaskConfig);
								relateTaskStatus = mgmTaskInfo.getIntValue("status");

								// 更新子任务关联状态和回执信息
								updateSubTaskRelateStatusAndMsg(curSubTask, relateTaskStatus,
										mgmTaskInfo.getString("errors"), logPrefix);

								if (relateTaskStatus == SubTaskDictConstants.RELATE_STATUS_RUNNING) {
									// 判断该子任务是否超时
									boolean timeout = isTimeout(curSubTask);
									if (timeout) {
										// 子任务执行超时后的业务处理
										executeAfterSubTaskTimeout(curSubTask, task);
										return;
									}
									Thread.sleep(dfSubTaskConfig.getSearchFrequency());
								}
							}

							// 任务失败
							if (relateTaskStatus != SubTaskDictConstants.RELATE_STATUS_DONE) {
								task.setMsg(curSubTask.getRelateTaskMsg());
								// 子任务执行成功失败后的业务处理
								executeAfterSubTaskFailure(curSubTask, task);
								return;
							}

						} else {
							switch (curSubTask.getMethodType()) {
							case HttpClientUtils.METHOD_DELETE:
								if (StringUtils.isNotBlank(curSubTask.getUrl())) {
									RespJson httpRespJson = sendHttpDelete(siteId, SysConstants.INTERFACE_TYPE_MGM,
											curSubTask.getUrl());
									if (httpRespJson.getStatus() != HttpStatus.SC_NO_CONTENT) {
										throw new APIException(httpRespJson.getMsg());
									}
								}
								break;
							case HttpClientUtils.METHOD_PUT:
								if (StringUtils.isNotBlank(curSubTask.getUrl())) {
									RespJson httpRespJson = sendHttpPut(siteId, SysConstants.INTERFACE_TYPE_MGM,
											curSubTask.getUrl(), curSubTask.getParam());
									if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
										throw new APIException(httpRespJson.getMsg());
									}
								}
								break;
							case HttpClientUtils.METHOD_POST:
								if (SubTaskDictConstants.ACTION_TYPE_ISOLATE.equals(curSubTask.getActionType())) {
									UnitEntity unit = (UnitEntity) task.getObj();
									ServEntity serv = servDao.getBase(unit.getSubServ().getServ().getId());

									// 服务类型
									String servType = serv.getOrder().getDefinitionServ().getName();

									if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
										// 子服务
										List<SubServEntity> subServs = serv.getSubServs();
										for (SubServEntity subServ : subServs) {
											// 子服务类型
											String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
											// switch_manager
											if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
												if (StringUtils.isNotBlank(subServ.getRelateId())) {
													// 从MGM获取指定服务的地址
													List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId,
															subServ.getRelateId(),
															subServ.getSubOrder().getDefinitionSubServ().getPortKey());

													if (ipAndPorts.size() == 0) {
														throw new APIException("获取不到swm地址");
													}

													Resp resp = null;
													for (Map<String, Object> ipAndPort : ipAndPorts) {
														String url = "http://" + (String) ipAndPort.get("ip") + ":"
																+ ipAndPort.get("port");
														try {
															resp = Smlib.Isolate(url, unit.getRelateName());
															if (resp.status == HttpStatus.SC_CREATED
																	|| resp.status == HttpStatus.SC_OK) {
																break;
															}
														} catch (Exception e) {
														}
													}

													if (resp == null || resp.status != HttpStatus.SC_CREATED
															&& resp.status != HttpStatus.SC_OK) {
														throw new APIException("调用swm隔离接口异常：" + resp.content);
													}
												}
											}
										}
									}

								} else if (SubTaskDictConstants.ACTION_TYPE_RECOVER
										.equals(curSubTask.getActionType())) {
									UnitEntity unit = (UnitEntity) task.getObj();
									ServEntity serv = servDao.getBase(unit.getSubServ().getServ().getId());

									// 服务类型
									String servType = serv.getOrder().getDefinitionServ().getName();

									if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
										// 子服务
										List<SubServEntity> subServs = serv.getSubServs();
										for (SubServEntity subServ : subServs) {
											// 子服务类型
											String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
											// switch_manager
											if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
												if (StringUtils.isNotBlank(subServ.getRelateId())) {
													// 从MGM获取指定服务的地址
													List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId,
															subServ.getRelateId(),
															subServ.getSubOrder().getDefinitionSubServ().getPortKey());

													if (ipAndPorts.size() == 0) {
														throw new APIException("获取不到swm地址");
													}

													Resp resp = null;
													for (Map<String, Object> ipAndPort : ipAndPorts) {
														String url = "http://" + (String) ipAndPort.get("ip") + ":"
																+ ipAndPort.get("port");
														try {
															resp = Smlib.Recover(url, unit.getRelateName());
															if (resp.status == HttpStatus.SC_CREATED
																	|| resp.status == HttpStatus.SC_OK) {
																break;
															}
														} catch (Exception e) {
														}
													}

													if (resp == null || resp.status != HttpStatus.SC_CREATED
															&& resp.status != HttpStatus.SC_OK) {
														throw new APIException("调用swm回切接口异常：" + resp.content);
													}
												}
											}
										}
									}
								}
								break;
							default:
								break;
							}
						}
						// 子任务执行成功后的业务处理
						executeAfterSubTaskSuccess(curSubTask, task);
					}
					// 任务执行成功后的业务处理
					executeAfterTaskSuccess(task);
				} catch (Exception e) {
					e.printStackTrace();
					logger.info(logPrefix + " - " + "异常:" + e.toString());
					task.setMsg(e.getMessage());
					executeAfterSubTaskFailure(curSubTask, task);
				}
			}
		});
	}

	/**
	 * 通用监控数据转换处理
	 */
	public JSONArray convertMonitorMetricData(JSONArray metrics) {
		JSONArray ret = new JSONArray();
		for (Object obj : metrics) {

			JSONObject metric = (JSONObject) obj;

			long timestamp = metric.getLongValue("timestamp") / 60 * 1000 * 60;
			metric.put("timestamp", timestamp);
			ret.add(metric);

		}

		return ret;
	}

	/**
	 * 通用获取历史监控数据
	 */
	public JSONArray getHistoryFromcommonType(JSONObject metricsObj) throws APIException {
		if (metricsObj.isEmpty()) {
			return new JSONArray();
		}

		if (!metricsObj.getBoolean("history")) {
			throw new APIException("the metric just get nohistory data");
		}

		JSONArray metrics = convertMonitorMetricData((JSONArray) metricsObj.getJSONArray("metrics"));

		return metrics;

	}

	/**
	 * 通用获取非历史监控数据
	 */

	public JSONObject getNoHistoryFromcommonType(JSONObject metricsObj) {

		if (metricsObj.isEmpty()) {
			return new JSONObject();
		}

		JSONArray metrics = convertMonitorMetricData((JSONArray) metricsObj.getJSONArray("metrics"));
		if (metrics.size() == 0) {
			return new JSONObject();
		}

		if (metrics.size() == 1) {
			return (JSONObject) metrics.get(0);
		}

		int index = 0;
		Long tmp = new Long(0);
		for (int i = 0; i < metrics.size(); i++) {

			JSONObject curMetric = (JSONObject) metrics.get(i);
			if (curMetric.getLong("timestamp") > tmp) {
				index = i;
				tmp = curMetric.getLong("timestamp");
			}
		}

		return (JSONObject) metrics.get(index);
	}

	private RespJson sendHttp(String siteId, String interfaceType, String url, String methodName, String jsonParam,
			int retryCnt, int timeInterval, boolean showLog) {
		RespJson httpRespJson = null;
		String httpUrl = consulCache.getHttpUrl(siteId, interfaceType);
		if (httpUrl == null) {
			String errorMsg = "";
			if (SysConstants.INTERFACE_TYPE_MGM.equals(interfaceType)) {
				errorMsg = "站点不存在或从consul上获取不到mgm地址";
			} else if (SysConstants.INTERFACE_TYPE_HS.equals(interfaceType)) {
				errorMsg = "站点不存在或从consul上获取不到horus地址";
			}
			logger.error(errorMsg);
			return RespJsonFactory.build(HttpStatus.SC_SERVICE_UNAVAILABLE, errorMsg);
		}
		try {
			httpUrl = httpUrl + url;
			if (HttpClientUtils.METHOD_POST.equals(methodName)) {
				httpRespJson = HttpClientUtils.sendHttpPost(httpUrl, jsonParam, showLog);
			} else if (HttpClientUtils.METHOD_PUT.equals(methodName)) {
				httpRespJson = HttpClientUtils.sendHttpPut(httpUrl, jsonParam, showLog);
			} else if (HttpClientUtils.METHOD_DELETE.equals(methodName)) {
				httpRespJson = HttpClientUtils.sendHttpDelete(httpUrl, showLog);
			} else if (HttpClientUtils.METHOD_GET.equals(methodName)) {
				httpRespJson = HttpClientUtils.sendHttpGet(httpUrl, showLog);
			}
		} catch (HttpConnectionException e) {
			try {
				consulCache.clean(siteId, interfaceType);
				if (retryCnt == 0) {
					String errorMsg = "请求超时";
					if (SysConstants.INTERFACE_TYPE_MGM.equals(interfaceType)) {
						errorMsg = "站点不存在或从consul上获取不到mgm地址";
					} else if (SysConstants.INTERFACE_TYPE_HS.equals(interfaceType)) {
						errorMsg = "站点不存在或从consul上获取不到horus地址";
					}
					logger.error(errorMsg);
					return RespJsonFactory.build(HttpStatus.SC_SERVICE_UNAVAILABLE, errorMsg);
				}
				Thread.sleep(timeInterval);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			logger.info("再次发送HTTP请求");
			httpRespJson = sendHttp(siteId, interfaceType, url, methodName, jsonParam, retryCnt - 1, timeInterval,
					showLog);
		} catch (Exception e) {
			consulCache.clean(siteId, interfaceType);
			logger.error("系统异常");
			return RespJsonFactory.build(HttpStatus.SC_INTERNAL_SERVER_ERROR, "系统异常");
		}
		return httpRespJson;
	}

	private void updateSubTaskToStart(SubTaskEntity subTask, String logPrefix) {
		subTask.setStartDateTime(systemDao.getCurrentDateTime());
		subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
		subTaskDao.updateToStart(subTask);
		String logDescr = logPrefix + " - " + LogUtils.formateUpdate("子任务表", new String[] { "子任务状态", "开始时间" }, subTask,
				new String[] { "id", "status", "startDateTime" });
		logger.info(logDescr);
	}

	private void updateSubTaskToEnd(SubTaskEntity subTask, String logPrefix) {
		subTask.setEndDateTime(systemDao.getCurrentDateTime());
		subTaskDao.updateToEnd(subTask);
		String logDescr = logPrefix + " - " + LogUtils.formateUpdate("子任务表", new String[] { "子任务状态", "结束时间" }, subTask,
				new String[] { "id", "status", "endDateTime" });
		logger.info(logDescr);
	}

	private void updateTaskToEnd(TaskEntity task, String logPrefix) {
		taskDao.updateToEnd(task);
		String logDescr = logPrefix + " - " + LogUtils.formateUpdate("任务表", new String[] { "任务状态", "任务回执", "结束时间" },
				task, new String[] { "id", "status", "msg", "endDateTime" });
		logger.info(logDescr);
	}

	private void updateSubTaskRelateId(SubTaskEntity subTask, String relateTaskId, String logPrefix) {
		subTask.setRelateTaskId(relateTaskId);
		subTaskDao.updateRelateId(subTask);
		String logDescr = logPrefix + " - " + LogUtils.formateUpdate("子任务表", new String[] { "关联子任务编码" }, subTask,
				new String[] { "id", "relateTaskId" });
		logger.info(logDescr);
	}

	private void updateSubTaskRelateStatusAndMsg(SubTaskEntity subTask, Integer relateStatus, String relateMsg,
			String logPrefix) {
		subTask.setRelateTaskStatus(relateStatus);
		subTask.setRelateTaskMsg(relateMsg);
		subTaskDao.updateRelateStatusAndMsg(subTask);
		String logDescr = logPrefix + " - " + LogUtils.formateUpdate("子任务表", new String[] { "关联子任务状态", "关联子任务回执" },
				subTask, new String[] { "id", "relateTaskStatus", "relateTaskMsg" });
		logger.info(logDescr);
	}

	private JSONObject getTaskInfoFromMGM(String siteId, String mgmTaskId,
			DefinitionSubTaskConfigEntity dfSubTaskConfig) throws APIException {
		String urlPattern = "/{0}/tasks/{1}";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION, mgmTaskId);
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url,
				dfSubTaskConfig.getSearchRetryCnt(), dfSubTaskConfig.getSearchRetryIntervalTime());
		if (httpRespJson.getStatus() == HttpStatus.SC_OK) {
			return ((JSONObject) httpRespJson.getData());
		} else {
			throw new APIException(httpRespJson.getMsg());
		}
	}

	/**
	 * 异步子任务执行后的业务处理
	 * 
	 * @param subTask
	 *            子任务对象
	 * @param task
	 *            任务对象
	 * @param respJson
	 *            子任务接口返回值
	 */
	private void executeAfterAsyncSubTask(SubTaskEntity subTask, TaskEntity task, JSONObject respJson) {
		String logPrefix = LogUtils.formate(task, subTask.getActionType() + "_" + subTask.getObjName());
		if (subTask.isAsync()) {
			// 更新子任务关联编码
			updateSubTaskRelateId(subTask, respJson.getString("task_id"), logPrefix);

			switch (subTask.getObjType()) {
			// 软件镜像
			case SubTaskDictConstants.OBJ_TYPE_SOFTWARE_IMAGE:
				switch (subTask.getActionType()) {
				// 创建
				case SubTaskDictConstants.ACTION_TYPE_CREATE:
					SubServSoftwareImageEntity subServSoftwareImage = (SubServSoftwareImageEntity) subTask.getObj();
					subServSoftwareImage.setRelateId(respJson.getString("id"));
					// 更新软件镜像关联编码
					updateSoftwareImageRelateId(subServSoftwareImage, logPrefix);
					break;
				}
				break;
			// 主机
			case SubTaskDictConstants.OBJ_TYPE_HOST:
				switch (subTask.getActionType()) {
				// 入库
				case SubTaskDictConstants.ACTION_TYPE_INPUT:
					HostEntity host = (HostEntity) subTask.getObj();
					host.setRelateId(respJson.getString("id"));
					// 更新主机关联编码
					updateHostRelateId(host, logPrefix);
					break;
				}
				break;
			// 子服务
			case SubTaskDictConstants.OBJ_TYPE_SUBSERV:
				switch (subTask.getActionType()) {
				// 创建
				case SubTaskDictConstants.ACTION_TYPE_CREATE:
					SubServEntity subServ = (SubServEntity) subTask.getObj();
					subServ.setRelateId(respJson.getString("id"));
					// 更新子服务关联编码
					updateSubServRelateId(subServ, logPrefix);

					// 更新单元关联编码
					updateUnitRelateIdAndName(subServ.getUnits(), respJson.getJSONArray("units"), logPrefix);
					break;
				// 启动
				case SubTaskDictConstants.ACTION_TYPE_START:
					break;
				// 停止
				case SubTaskDictConstants.ACTION_TYPE_STOP:
					break;
				// 扩容
				case SubTaskDictConstants.ACTION_TYPE_SCALE_UP:
					break;
				// 版本变更
				case SubTaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
					break;
				// 重建
				case SubTaskDictConstants.ACTION_TYPE_REBUILD:
					break;
				}
				break;
			// 单元
			case SubTaskDictConstants.OBJ_TYPE_UNIT:
				switch (subTask.getActionType()) {
				// 启动
				case SubTaskDictConstants.ACTION_TYPE_START:
					break;
				// 停止
				case SubTaskDictConstants.ACTION_TYPE_STOP:
					break;
				// 备份
				case SubTaskDictConstants.ACTION_TYPE_BACKUP:
					break;
				// 还原
				case SubTaskDictConstants.ACTION_TYPE_RESTORE:
					break;
				// 迁移
				case SubTaskDictConstants.ACTION_TYPE_MIGRATE:
					break;
				// 重建
				case SubTaskDictConstants.ACTION_TYPE_REBUILD:
					break;
				}
				break;
			}
		}
	}

	/**
	 * 子任务执行成功后的业务处理
	 * 
	 * @param subTask
	 *            子任务对象
	 * @param task
	 *            任务对象
	 * @throws APIException
	 */
	private void executeAfterSubTaskSuccess(SubTaskEntity subTask, TaskEntity task) throws APIException {
		String logPrefix = LogUtils.formate(task, subTask.getActionType() + "_" + subTask.getObjName());
		switch (subTask.getObjType()) {
		// 软件镜像
		case SubTaskDictConstants.OBJ_TYPE_SOFTWARE_IMAGE:
			switch (subTask.getActionType()) {
			// 创建
			case SubTaskDictConstants.ACTION_TYPE_CREATE:
				break;
			}
			break;
		// 主机
		case SubTaskDictConstants.OBJ_TYPE_HOST:
			HostEntity host = (HostEntity) subTask.getObj();
			switch (subTask.getActionType()) {
			// 入库
			case SubTaskDictConstants.ACTION_TYPE_INPUT:
				break;
			// 出库
			case SubTaskDictConstants.ACTION_TYPE_OUTPUT:
				host.setRelateId(null);
				// 更新主机关联编码
				updateHostRelateId(host, logPrefix);
				break;
			// 启用
			case SubTaskDictConstants.ACTION_TYPE_ENABLE:
				break;
			// 停用
			case SubTaskDictConstants.ACTION_TYPE_DISABLE:
				break;
			}
			break;
		// 子服务
		case SubTaskDictConstants.OBJ_TYPE_SUBSERV:
			SubServEntity subServ = (SubServEntity) subTask.getObj();
			switch (subTask.getActionType()) {
			// 创建
			case SubTaskDictConstants.ACTION_TYPE_CREATE:
				break;
			// 删除
			case SubTaskDictConstants.ACTION_TYPE_REMOVE:
				switch (task.getActionType()) {
				case TaskDictConstants.ACTION_TYPE_REMOVE:
					// 删除子服务及关联信息
					removeSubServ(subServ, logPrefix);
					break;
				case TaskDictConstants.ACTION_TYPE_REBUILD:
					subServ.setRelateId(null);
					// 更新子服务关联编码
					updateSubServRelateId(subServ, logPrefix);

					// 更新单元关联编码
					updateUnitRelateIdAndName(subServ.getUnits(), null, logPrefix);
					break;
				}
				break;
			// 启动
			case SubTaskDictConstants.ACTION_TYPE_START:
				break;
			// 停止
			case SubTaskDictConstants.ACTION_TYPE_STOP:
				break;
			// 扩容
			case SubTaskDictConstants.ACTION_TYPE_SCALE_UP:
				break;
			// 版本变更
			case SubTaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
				break;
			// 重建
			case SubTaskDictConstants.ACTION_TYPE_REBUILD:
				break;
			}
			break;
		// 单元
		case SubTaskDictConstants.OBJ_TYPE_UNIT:
			switch (subTask.getActionType()) {
			// 启动
			case SubTaskDictConstants.ACTION_TYPE_START:
				break;
			// 停止
			case SubTaskDictConstants.ACTION_TYPE_STOP:
				break;
			// 备份
			case SubTaskDictConstants.ACTION_TYPE_BACKUP:
				break;
			// 还原
			case SubTaskDictConstants.ACTION_TYPE_RESTORE:
				break;
			// 迁移
			case SubTaskDictConstants.ACTION_TYPE_MIGRATE:
				break;
			// 重建
			case SubTaskDictConstants.ACTION_TYPE_REBUILD:
				break;
			// 隔离
			case SubTaskDictConstants.ACTION_TYPE_ISOLATE:
				break;
			// 回切
			case SubTaskDictConstants.ACTION_TYPE_RECOVER:
				break;
			}
			break;
		}

		// 子任务成功
		subTask.setStatus(SubTaskDictConstants.STATUS_SUCCESS);
		subTask.setEndDateTime(systemDao.getCurrentDateTime());
		// 更新子任务结束时间和状态
		updateSubTaskToEnd(subTask, logPrefix);
	}

	/**
	 * 子任务执行失败后的业务处理
	 * 
	 * @param subTask
	 *            子任务对象
	 * @param task
	 *            任务对象
	 */
	private void executeAfterSubTaskFailure(SubTaskEntity subTask, TaskEntity task) {
		String logPrefix = LogUtils.formate(task, subTask.getActionType() + "_" + subTask.getObjName());
		subTask.setStatus(SubTaskDictConstants.STATUS_FAILURE);
		updateSubTaskToEnd(subTask, logPrefix);

		task.setStatus(getTaskFailureStatus(task));
		task.setEndDateTime(subTask.getEndDateTime());
		updateTaskToEnd(task, logPrefix);
	}

	/**
	 * 子任务执行超时后的业务处理
	 * 
	 * @param subTask
	 *            子任务对象
	 * @param task
	 *            任务对象
	 */
	private void executeAfterSubTaskTimeout(SubTaskEntity subTask, TaskEntity task) {
		String logPrefix = LogUtils.formate(task, subTask.getActionType() + "_" + subTask.getObjName());
		subTask.setStatus(SubTaskDictConstants.STATUS_UNKNOWN);
		updateSubTaskToEnd(subTask, logPrefix);

		task.setStatus(TaskDictConstants.STATUS_UNKNOWN);
		task.setEndDateTime(subTask.getEndDateTime());
		task.setMsg("任务超时");
		updateTaskToEnd(task, logPrefix);
	}

	/**
	 * 任务执行成功后的处理
	 * 
	 * @param task
	 *            任务对象
	 */
	private void executeAfterTaskSuccess(TaskEntity task) {
		String logPrefix = LogUtils.formate(task, null);
		switch (task.getObjType()) {
		// 软件镜像
		case TaskDictConstants.OBJ_TYPE_SOFTWARE_IMAGE:
			SubServSoftwareImageEntity subServSoftwareImage = (SubServSoftwareImageEntity) task.getObj();
			switch (task.getActionType()) {
			// 创建
			case TaskDictConstants.ACTION_TYPE_CREATE:
				updateSoftwareImageEnabled(subServSoftwareImage, logPrefix);
				break;
			}
			break;
		// 主机
		case TaskDictConstants.OBJ_TYPE_HOST:
			HostEntity host = (HostEntity) task.getObj();
			switch (task.getActionType()) {
			// 入库
			case TaskDictConstants.ACTION_TYPE_INPUT:
				host.setStatus(DictConstants.HOST_STATUS_ENABLE);
				hostDao.updateStatus(host);
				break;
			// 出库
			case TaskDictConstants.ACTION_TYPE_OUTPUT:
				host.setStatus(DictConstants.HOST_STATUS_INPUT_NO);
				hostDao.updateStatus(host);
				break;
			// 启用
			case TaskDictConstants.ACTION_TYPE_ENABLE:
				host.setStatus(DictConstants.HOST_STATUS_ENABLE);
				hostDao.updateStatus(host);
				break;
			// 停用
			case TaskDictConstants.ACTION_TYPE_DISABLE:
				host.setStatus(DictConstants.HOST_STATUS_DISABLE);
				hostDao.updateStatus(host);
				break;
			}
			break;
		// 服务
		case TaskDictConstants.OBJ_TYPE_SERV:
			ServEntity serv = (ServEntity) task.getObj();
			switch (task.getActionType()) {
			// 创建
			case TaskDictConstants.ACTION_TYPE_CREATE:
				break;
			// 删除
			case TaskDictConstants.ACTION_TYPE_REMOVE:
				// 删除服务及关联信息
				removeServ(serv, logPrefix);
				break;
			// 启动
			case TaskDictConstants.ACTION_TYPE_START:
				break;
			// 停止
			case TaskDictConstants.ACTION_TYPE_STOP:
				break;
			// 备份
			case TaskDictConstants.ACTION_TYPE_BACKUP:
				break;
			// 扩容
			case TaskDictConstants.ACTION_TYPE_SCALE_UP:
				break;
			// 版本变更
			case TaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
				break;
			// 重建
			case TaskDictConstants.ACTION_TYPE_REBUILD:
				break;
			}
			break;
		// 单元
		case TaskDictConstants.OBJ_TYPE_UNIT:
			switch (task.getActionType()) {
			// 启动
			case TaskDictConstants.ACTION_TYPE_START:
				break;
			// 停止
			case TaskDictConstants.ACTION_TYPE_STOP:
				break;
			// 备份
			case TaskDictConstants.ACTION_TYPE_BACKUP:
				break;
			// 还原
			case TaskDictConstants.ACTION_TYPE_RESTORE:
				break;
			// 迁移
			case TaskDictConstants.ACTION_TYPE_MIGRATE:
				break;
			// 重建
			case TaskDictConstants.ACTION_TYPE_REBUILD:
				break;
			// 隔离
			case TaskDictConstants.ACTION_TYPE_ISOLATE:
				break;
			// 回切
			case TaskDictConstants.ACTION_TYPE_RECOVER:
				break;
			}
			break;
		}

		String status = getTaskSuccessStatus(task);
		task.setStatus(status);
		task.setEndDateTime(getLastSubTaskEndTime(task));
		// 任务成功
		// 更新任务结束时间和状态
		updateTaskToEnd(task, logPrefix);
	}

	/**
	 * 获取指定任务的最终子任务的结束时间
	 * 
	 * @param task
	 *            任务对象
	 * @return
	 */
	private Date getLastSubTaskEndTime(TaskEntity task) {
		Date date = task.getStartDateTime();
		List<SubTaskEntity> subTasks = task.getSubTasks();
		for (SubTaskEntity subTask : subTasks) {
			if (subTask.getEndDateTime() != null) {
				if (date.compareTo(subTask.getEndDateTime()) < 0) {
					date = subTask.getEndDateTime();
				}
			}
		}
		return date;
	}

	/**
	 * 获取任务成功时的状态
	 * 
	 * @param task
	 *            任务对象
	 * @return
	 */
	private String getTaskSuccessStatus(TaskEntity task) {
		String status = null;
		switch (task.getObjType()) {
		// 软件镜像
		case TaskDictConstants.OBJ_TYPE_SOFTWARE_IMAGE:
			switch (task.getActionType()) {
			// 创建
			case TaskDictConstants.ACTION_TYPE_CREATE:
				status = TaskDictConstants.STATUS_CREATE_SUCCESS;
				break;
			}
			break;
		// 主机
		case TaskDictConstants.OBJ_TYPE_HOST:
			switch (task.getActionType()) {
			// 入库
			case TaskDictConstants.ACTION_TYPE_INPUT:
				status = TaskDictConstants.STATUS_INPUT_SUCCESS;
				break;
			// 出库
			case TaskDictConstants.ACTION_TYPE_OUTPUT:
				status = TaskDictConstants.STATUS_OUTPUT_SUCCESS;
				break;
			// 启用
			case TaskDictConstants.ACTION_TYPE_ENABLE:
				status = TaskDictConstants.STATUS_ENABLE_SUCCESS;
				break;
			// 停用
			case TaskDictConstants.ACTION_TYPE_DISABLE:
				status = TaskDictConstants.STATUS_DISABLE_SUCCESS;
				break;
			}
			break;
		// 服务
		case TaskDictConstants.OBJ_TYPE_SERV:
			switch (task.getActionType()) {
			// 创建
			case TaskDictConstants.ACTION_TYPE_CREATE:
				status = TaskDictConstants.STATUS_CREATE_SUCCESS;
				break;
			// 删除
			case TaskDictConstants.ACTION_TYPE_REMOVE:
				status = TaskDictConstants.STATUS_REMOVE_SUCCESS;
				break;
			// 启动
			case TaskDictConstants.ACTION_TYPE_START:
				status = TaskDictConstants.STATUS_START_SUCCESS;
				break;
			// 停止
			case TaskDictConstants.ACTION_TYPE_STOP:
				status = TaskDictConstants.STATUS_STOP_SUCCESS;
				break;
			// 备份
			case TaskDictConstants.ACTION_TYPE_BACKUP:
				status = TaskDictConstants.STATUS_BACKUP_SUCCESS;
				break;
			// 扩容
			case TaskDictConstants.ACTION_TYPE_SCALE_UP:
				status = TaskDictConstants.STATUS_SCALE_UP_SUCCESS;
				break;
			// 版本变更
			case TaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
				status = TaskDictConstants.STATUS_IMAGE_UPDATE_SUCCESS;
				break;
			// 重建
			case TaskDictConstants.ACTION_TYPE_REBUILD:
				List<SubTaskEntity> subTasks = task.getSubTasks();
				for (SubTaskEntity subTask : subTasks) {
					switch (subTask.getActionType()) {
					case SubTaskDictConstants.ACTION_TYPE_CREATE:
						return TaskDictConstants.STATUS_CREATE_SUCCESS;
					case SubTaskDictConstants.ACTION_TYPE_SCALE_UP:
						return TaskDictConstants.STATUS_SCALE_UP_SUCCESS;
					case SubTaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
						return TaskDictConstants.STATUS_IMAGE_UPDATE_SUCCESS;
					}
				}
				break;
			}
			break;
		// 单元
		case TaskDictConstants.OBJ_TYPE_UNIT:
			switch (task.getActionType()) {
			// 启动
			case TaskDictConstants.ACTION_TYPE_START:
				status = TaskDictConstants.STATUS_START_SUCCESS;
				break;
			// 停止
			case TaskDictConstants.ACTION_TYPE_STOP:
				status = TaskDictConstants.STATUS_STOP_SUCCESS;
				break;
			// 备份
			case TaskDictConstants.ACTION_TYPE_BACKUP:
				status = TaskDictConstants.STATUS_BACKUP_SUCCESS;
				break;
			// 还原
			case TaskDictConstants.ACTION_TYPE_RESTORE:
				status = TaskDictConstants.STATUS_RESTORE_SUCCESS;
				break;
			// 迁移
			case TaskDictConstants.ACTION_TYPE_MIGRATE:
				status = TaskDictConstants.STATUS_MIGRATE_SUCCESS;
				break;
			// 重建
			case TaskDictConstants.ACTION_TYPE_REBUILD:
				status = TaskDictConstants.STATUS_REBUILD_SUCCESS;
				break;
			// 隔离
			case TaskDictConstants.ACTION_TYPE_ISOLATE:
				status = TaskDictConstants.STATUS_ISOLATE_SUCCESS;
				break;
			// 回切
			case TaskDictConstants.ACTION_TYPE_RECOVER:
				status = TaskDictConstants.STATUS_RECOVER_SUCCESS;
				break;
			}
			break;
		}
		return status;
	}

	/**
	 * 获取任务失败时的状态
	 * 
	 * @param task
	 *            任务对象
	 * @return
	 */
	private String getTaskFailureStatus(TaskEntity task) {
		String status = null;
		switch (task.getObjType()) {
		// 软件镜像
		case TaskDictConstants.OBJ_TYPE_SOFTWARE_IMAGE:
			switch (task.getActionType()) {
			// 创建
			case TaskDictConstants.ACTION_TYPE_CREATE:
				status = TaskDictConstants.STATUS_CREATE_FAILURE;
				break;
			}
			break;
		// 主机
		case TaskDictConstants.OBJ_TYPE_HOST:
			switch (task.getActionType()) {
			// 入库
			case TaskDictConstants.ACTION_TYPE_INPUT:
				status = TaskDictConstants.STATUS_INPUT_FAILURE;
				break;
			// 出库
			case TaskDictConstants.ACTION_TYPE_OUTPUT:
				status = TaskDictConstants.STATUS_OUTPUT_FAILURE;
				break;
			// 启用
			case TaskDictConstants.ACTION_TYPE_ENABLE:
				status = TaskDictConstants.STATUS_ENABLE_FAILURE;
				break;
			// 停用
			case TaskDictConstants.ACTION_TYPE_DISABLE:
				status = TaskDictConstants.STATUS_DISABLE_FAILURE;
				break;
			}
			break;
		// 服务
		case TaskDictConstants.OBJ_TYPE_SERV:
			switch (task.getActionType()) {
			// 创建
			case TaskDictConstants.ACTION_TYPE_CREATE:
				status = TaskDictConstants.STATUS_CREATE_FAILURE;
				break;
			// 删除
			case TaskDictConstants.ACTION_TYPE_REMOVE:
				status = TaskDictConstants.STATUS_REMOVE_FAILURE;
				break;
			// 启动
			case TaskDictConstants.ACTION_TYPE_START:
				status = TaskDictConstants.STATUS_START_FAILURE;
				break;
			// 停止
			case TaskDictConstants.ACTION_TYPE_STOP:
				status = TaskDictConstants.STATUS_STOP_FAILURE;
				break;
			// 备份
			case TaskDictConstants.ACTION_TYPE_BACKUP:
				status = TaskDictConstants.STATUS_BACKUP_FAILURE;
				break;
			// 扩容
			case TaskDictConstants.ACTION_TYPE_SCALE_UP:
				status = TaskDictConstants.STATUS_SCALE_UP_FAILURE;
				break;
			// 版本变更
			case TaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
				status = TaskDictConstants.STATUS_IMAGE_UPDATE_FAILURE;
				break;
			// 重建
			case TaskDictConstants.ACTION_TYPE_REBUILD:
				List<SubTaskEntity> subTasks = task.getSubTasks();
				for (SubTaskEntity subTask : subTasks) {
					switch (subTask.getActionType()) {
					case SubTaskDictConstants.ACTION_TYPE_CREATE:
						return TaskDictConstants.STATUS_CREATE_FAILURE;
					case SubTaskDictConstants.ACTION_TYPE_SCALE_UP:
						return TaskDictConstants.STATUS_SCALE_UP_FAILURE;
					case SubTaskDictConstants.ACTION_TYPE_IMAGE_UPDATE:
						return TaskDictConstants.STATUS_IMAGE_UPDATE_FAILURE;
					}
				}
				break;
			}
			break;
		// 单元
		case TaskDictConstants.OBJ_TYPE_UNIT:
			switch (task.getActionType()) {
			// 启动
			case TaskDictConstants.ACTION_TYPE_START:
				status = TaskDictConstants.STATUS_START_FAILURE;
				break;
			// 停止
			case TaskDictConstants.ACTION_TYPE_STOP:
				status = TaskDictConstants.STATUS_STOP_FAILURE;
				break;
			// 备份
			case TaskDictConstants.ACTION_TYPE_BACKUP:
				status = TaskDictConstants.STATUS_BACKUP_FAILURE;
				break;
			// 还原
			case TaskDictConstants.ACTION_TYPE_RESTORE:
				status = TaskDictConstants.STATUS_RESTORE_FAILURE;
				break;
			// 迁移
			case TaskDictConstants.ACTION_TYPE_MIGRATE:
				status = TaskDictConstants.STATUS_MIGRATE_FAILURE;
				break;
			// 重建
			case TaskDictConstants.ACTION_TYPE_REBUILD:
				status = TaskDictConstants.STATUS_REBUILD_FAILURE;
				break;
			// 隔离
			case TaskDictConstants.ACTION_TYPE_ISOLATE:
				status = TaskDictConstants.STATUS_ISOLATE_FAILURE;
				break;
			// 回切
			case TaskDictConstants.ACTION_TYPE_RECOVER:
				status = TaskDictConstants.STATUS_RECOVER_FAILURE;
				break;
			}
			break;
		}
		return status;
	}

	private void updateSoftwareImageRelateId(SubServSoftwareImageEntity image, String logPrefix) {
		subServSoftwareImageDao.updateRelateId(image);
		String logDescr = logPrefix + " - "
				+ LogUtils.formateUpdate("子服务软件镜像表", new String[] { "关联编码" }, image, new String[] { "id", "relateId" });
		logger.info(logDescr);
	}

	private void updateSoftwareImageEnabled(SubServSoftwareImageEntity subServSoftwareImage, String logPrefix) {
		subServSoftwareImage.setEnabled(true);
		subServSoftwareImageDao.updateEnabled(subServSoftwareImage);
		String logDescr = logPrefix + " - " + LogUtils.formateUpdate("子服务软件镜像表", new String[] { "可用状态" },
				subServSoftwareImage, new String[] { "id", "enabled" });
		logger.info(logDescr);
	}

	private void updateHostRelateId(HostEntity host, String logPrefix) {
		hostDao.updateRelateId(host);
		String logDescr = logPrefix + " - "
				+ LogUtils.formateUpdate("主机表", new String[] { "关联编码" }, host, new String[] { "id", "relateId" });
		logger.info(logDescr);
	}

	private void updateSubServRelateId(SubServEntity subServ, String logPrefix) {
		subServDao.updateRelateId(subServ);
		String logDescr = logPrefix + " - "
				+ LogUtils.formateUpdate("子服务表", new String[] { "关联编码" }, subServ, new String[] { "id", "relateId" });
		logger.info(logDescr);
	}

	private void updateUnitRelateIdAndName(List<UnitEntity> units, JSONArray relateUnits, String logPrefix) {
		for (int i = 0; i < units.size(); i++) {
			UnitEntity unit = units.get(i);
			if (relateUnits != null) {
				JSONObject unitInfo = relateUnits.getJSONObject(i);
				unit.setRelateId(unitInfo.getString("id"));
				unit.setRelateName(unitInfo.getString("name"));
			} else {
				unit.setRelateId(null);
				unit.setRelateName(null);
			}
			unitDao.updateRelateIdAndName(unit);
			String logDescr = logPrefix + " - " + LogUtils.formateUpdate("单元表", new String[] { "关联编码", "关联名称" }, unit,
					new String[] { "id", "relateId", "relateName" });
			logger.info(logDescr);
		}
	}

	private void removeSubServ(SubServEntity subServ, String logPrefix) {
		subServDao.removeRelativeUnit(subServ.getId());
		subServDao.remove(subServ.getId());
		portDao.updatePortToUnused(subServ.getPort());
		String servName = subServ.getSubOrder().getDefinitionSubServ().getName();
		String logDescr = logPrefix + " - 删除子服务(" + servName + ")及单元并释放子服务使用的端口";
		logger.info(logDescr);
	}

	private void removeServ(ServEntity serv, String logPrefix) {
		servDao.remove(serv.getId());
		backupStrategyDao.removeByServId(serv.getId());
		String logDescr = logPrefix + " - 删除服务及备份策略";
		logger.info(logDescr);
	}

	/**
	 * 获取指定服务的拓扑
	 * 
	 * @param serv
	 *            服务对象
	 * @return JSONObject 拓扑
	 * @throws APIException
	 *             API异常处理类
	 */
	public JSONObject getTopology(ServEntity serv) throws APIException {
		JSONObject topologyInfo = null;

		// 站点
		String siteId = serv.getOrder().getArea().getSite().getId();
		// 服务类型
		String servType = serv.getOrder().getDefinitionServ().getName();

		if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
				if (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)) {
					if (StringUtils.isNotBlank(subServ.getRelateId())) {
						// 从MGM获取指定服务的地址
						List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
								subServ.getSubOrder().getDefinitionSubServ().getPortKey());

						if (ipAndPorts.size() == 0) {
							throw new APIException("获取不到swm地址");
						}

						Resp resp = null;
						for (Map<String, Object> ipAndPort : ipAndPorts) {
							String url = "http://" + (String) ipAndPort.get("ip") + ":" + ipAndPort.get("port");
							try {
								resp = Smlib.GetTopology(url);
								if (resp.status == HttpStatus.SC_OK) {
									topologyInfo = JSONObject.parseObject(resp.content);
									return topologyInfo;
								}
							} catch (Exception e) {
							}
						}
						if (resp == null || resp.status != HttpStatus.SC_OK) {
							throw new APIException("调用swm拓扑接口异常:" + resp.content);
						}
					}
				}
			}
		} else if (SysConstants.SERV_UPREDIS_URPROXY_SENTINEL_CODE.equals(servType)) {
			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			Map<String, JSONArray> monitorUnitRoleMap = new HashMap<>();
			for (SubServEntity subServ : subServs) {
				// 子服务类型
				String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
				if (SysConstants.SUBSERV_UPREDIS_NAME.equals(dfServType)) {
					String metric = definitionMetricCache.getMetric(dfServType, "role");
					try {
						if (StringUtils.isNotBlank(subServ.getRelateId())) {
							monitorUnitRoleMap.putAll(getNohistory(siteId, metric, subServ.getRelateId()));
						}
					} catch (APIException e) {
					}
				}
			}
			topologyInfo = new JSONObject();
			for (Map.Entry<String, JSONArray> entry : monitorUnitRoleMap.entrySet()) {
				topologyInfo.put(entry.getKey(), entry.getValue());
			}
		}
		return topologyInfo;
	}

	/**
	 * 获取主单元关联名称
	 * 
	 * @param serv
	 *            服务对象
	 * @return Map key: 子服务关联编码；value: 单元关联名称
	 * @throws APIException
	 */
	public Map<String, String> getMasterUnitRelateName(ServEntity serv) throws APIException {
		Map<String, String> masterMap = new HashMap<>();
		// 服务类型
		String servType = serv.getOrder().getDefinitionServ().getName();
		if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)) {
			JSONObject topologyInfo = getTopology(serv);
			if (topologyInfo != null) {
				JSONObject groupInfo = topologyInfo.getJSONObject("datanode_group");
				if (groupInfo != null) {
					for (Map.Entry<String, Object> subServ : groupInfo.entrySet()) {
						String unitRelateName = null;
						JSONObject subServInfo = (JSONObject) subServ.getValue();
						for (Map.Entry<String, Object> unit : subServInfo.entrySet()) {
							JSONObject unitInfo = (JSONObject) unit.getValue();
							if ("master".equals(unitInfo.getString("type"))
									&& "normal".equals(unitInfo.getString("status"))) {
								unitRelateName = unit.getKey();
								break;
							}
						}
						masterMap.put(subServ.getKey(), unitRelateName);
					}
				}
			}
		}
		return masterMap;
	}

	/**
	 * 是否存在主
	 * 
	 * @param masterMap
	 * @return
	 */
	public boolean existMaster(Map<String, String> masterMap) {
		boolean exist = false;
		for (Map.Entry<String, String> entry : masterMap.entrySet()) {
			if (StringUtils.isNotBlank(entry.getValue())) {
				exist = true;
				break;
			}
		}
		return exist;
	}

	/**
	 * 从MGM获取指定服务的地址
	 * 
	 * @param siteId
	 *            站点编码
	 * @param mgmServId
	 *            mgm服务编码
	 * @param mgmPortKey
	 *            mgm端口Key
	 * @return 服务地址
	 * @throws APIException
	 *             API异常处理类
	 */
	public List<Map<String, Object>> listIpAndPortFromMGM(String siteId, String mgmServId, String mgmPortKey)
			throws APIException {
		List<Map<String, Object>> ipAndPorts = new ArrayList<>();
		JSONObject mgmServInfo = getServInfoFromMGM(siteId, mgmServId);
		if (mgmServInfo != null) {
			JSONObject optsJson = mgmServInfo.getJSONObject("opts");
			JSONArray unitInfos = mgmServInfo.getJSONArray("units");
			for (int i = 0; i < unitInfos.size(); i++) {
				JSONObject unitInfo = unitInfos.getJSONObject(i);
				JSONArray networkingsInfo = unitInfo.getJSONArray("networkings");
				Map<String, Object> map = new HashMap<>();
				map.put("ip", networkingsInfo.getJSONObject(0).getString("ip_addr"));
				map.put("port", optsJson.getInteger(mgmPortKey));
				ipAndPorts.add(map);
			}
		}
		return ipAndPorts;
	}

	/**
	 * 获取LINK时的参数
	 * 
	 * @param serv
	 *            服务对象
	 * @return String LINK时所需的参数
	 */
	public String getLinkParam(ServEntity serv, String mgmUnitId) {
		JSONObject jsonParam = new JSONObject();
		String mode = null;
		String defitionServCode = serv.getOrder().getDefinitionServ().getCode();
		if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(defitionServCode)) {
			mode = "SwitchManager_Upproxy_UpSQL";
		} else if (SysConstants.SERV_UPREDIS_URPROXY_SENTINEL_CODE.equals(defitionServCode)) {
			mode = "Sentinel_Urproxy_Upredis";
		}
		jsonParam.put("mode", mode);
		if (StringUtils.isNotBlank(mgmUnitId)) {
			jsonParam.put("nameOrID", mgmUnitId);
		}
		JSONArray links = new JSONArray();
		jsonParam.put("links", links);
		List<DefinitionSubServRelationEntity> relations = definitionSubServRelationDao
				.listByDefinitionServCode(defitionServCode);
		for (DefinitionSubServRelationEntity relation : relations) {
			List<String> fromSubServRelateIds = subServDao.listRelateIdByServIdAndDfSubServName(serv.getId(),
					relation.getFromDefinitionSubServName());
			for (String fromSubServRelateId : fromSubServRelateIds) {
				JSONObject link = new JSONObject();
				links.add(link);

				link.put("id", fromSubServRelateId);
				List<String> toSubServNames = relation.getToDefinitionSubServNames();
				JSONArray deps = new JSONArray();
				link.put("deps", deps);
				for (String subServName : toSubServNames) {
					List<String> toSubServRelateIds = subServDao.listRelateIdByServIdAndDfSubServName(serv.getId(),
							subServName);
					deps.addAll(toSubServRelateIds);
				}
			}
		}
		return jsonParam.toJSONString();
	}

	/**
	 * 从MGM获取指定的服务信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @param mgmServId
	 *            mgm服务编码
	 * @return MGM服务信息
	 * @throws APIException
	 *             API异常处理类
	 */
	public JSONObject getServInfoFromMGM(String siteId, String mgmServId) throws APIException {
		String urlPattern = "/{0}/services/{1}";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION, mgmServId);
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url);
		if (httpRespJson.getStatus() == HttpStatus.SC_OK) {
			return ((JSONObject) httpRespJson.getData());
		} else {
			throw new APIException(httpRespJson.getMsg());
		}
	}

	/**
	 * 执行MGM exec接口
	 * 
	 * @param siteId
	 *            站点编码
	 * @param mgmServId
	 *            mgm服务编码
	 * @param param
	 *            请求参数
	 * @return String 数据库信息
	 * @throws APIException
	 *             API异常处理类
	 */
	public String executeMgmExec(String siteId, String mgmServId, String param) throws APIException {
		String urlPattern = "/{0}/services/{1}/exec?sync=true";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION, mgmServId);
		RespJson httpRespJson = sendHttpPost(siteId, SysConstants.INTERFACE_TYPE_MGM, url, param);
		if (httpRespJson.getStatus() != HttpStatus.SC_CREATED) {
			throw new APIException(httpRespJson.getMsg());
		}
		JSONObject respJson = (JSONObject) httpRespJson.getData();
		if (respJson.getIntValue("code") != 0) {
			throw new APIException(respJson.getString("output"));
		}
		return respJson.getString("output");
	}

	public Map<String, JSONArray> getNohistory(String siteId, String metric, String tag) throws APIException {
		long end = System.currentTimeMillis() / 1000;
		long start = end - 60 * 2;
		JSONArray ret = getMetrisWithTagFromHorus(siteId, metric, end, start, tag);

		JSONArray units = new JSONArray();

		for (Object tmp : ret) {
			units.add(getNoHistoryFromcommonType((JSONObject) tmp));
		}

		return getSubServMap(units);
	}

	private JSONArray getMetrisWithTagFromHorus(String siteId, String metric, long end, long start, String tag)
			throws APIException {
		String url = null;

		if (tag != null) {
			url = String.format("/%s/units?start_time=%d&end_time=%d&metric=%s&tag=%s", SysConstants.HS_VERSION, start,
					end, metric, tag);
		} else {
			url = String.format("/%s/units?start_time=%d&end_time=%d&metric=%s", SysConstants.HS_VERSION, start, end,
					metric);
		}

		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_HS, url);

		if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
			logger.error("get horus fail:" + httpRespJson);
			throw new APIException(httpRespJson.getMsg());

		}

		return (JSONArray) httpRespJson.getData();
	}

	private Map<String, JSONArray> getSubServMap(JSONArray metrics) {
		Map<String, JSONArray> maps = new HashMap<String, JSONArray>();

		for (Object tmp : metrics) {
			String key = ((JSONObject) tmp).getString("tag");
			if (maps.containsKey(key)) {
				maps.get(key).add(tmp);
			} else {
				maps.put(key, new JSONArray());
				maps.get(key).add(tmp);
			}

		}

		return maps;
	}

}
